package com.andova.glcamera

import android.content.Intent
import android.graphics.ImageFormat
import android.graphics.Rect
import android.graphics.YuvImage
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.view.MotionEvent
import android.view.View
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import com.andova.camera.EmptyActivity
import com.andova.ext.d
import com.andova.ext.i
import com.andova.glcamera.device.*
import com.andova.glcamera.texture.TextureFrameCallback
import com.andova.opengles.databinding.AcGlCameraViewBinding
import java.io.File
import java.io.FileOutputStream
import java.util.*

const val X_UNIT = 1.77777777f

class GlCameraViewActivity : AppCompatActivity(), StateCallback {
    private lateinit var mBinding: AcGlCameraViewBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mBinding = AcGlCameraViewBinding.inflate(layoutInflater)
        setContentView(mBinding.root)
    }

    override fun onOpened(cameraId: String) {
        d("state -> onOpened $cameraId")
    }

    override fun onClosed(cameraId: String) {
        d("state -> onClosed $cameraId")
    }

    override fun onDisconnected(cameraId: String) {
        d("state -> onDisconnected $cameraId")
    }

    override fun onError(cameraId: String) {
        d("state -> onError $cameraId")
    }

    private val handler = object : GlFrameHandler {
        override fun strict(): Boolean = false
        override fun handleFrame(cam0buf: FrameBuffer?, cam1buf: FrameBuffer?, syncBuffer: SyncFrameBuffer?, taskResult: Any?) {
//            methodTime {
//                decodeNv21ToFile(cam0buf?.nv21 ?: return@methodTime, cam0buf.width, cam0buf.height, ANGLE_90)
//            }

//            syncBuffer ?: return
//            rgbBuffer ?: return
//            printCounter()
            i("rgbBuffer:${cam0buf?.nv21?.size}, irBuffer:${cam1buf?.nv21?.size}, syncBuffer:[${syncBuffer?.cam0Buffer?.nv21?.size}, ${syncBuffer?.cam1Buffer?.nv21?.size}]")
        }
    }

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    override fun onResume() {
        super.onResume()
        mBinding.backcamera.useTextureRender(object : TextureFrameCallback {
            override fun onTaskFrame(imageWidth: Int, imageHeight: Int, nv21: ByteArray, handlerResult: Any?): Any? {
                return null
            }
        }, object : CameraBuilder() {
            override fun stateCallback() = this@GlCameraViewActivity
            override fun previewSize(sizes: SortedSet<Size>?): Size? {
                return when {
                    sizes?.size ?: 0 > 2 -> sizes?.elementAt(2)
                    sizes?.size ?: 0 > 3 -> sizes?.elementAt(3)
                    else -> sizes?.first()
                }
            }

            override fun pictureSize(sizes: SortedSet<Size>?): Size? {
                return when {
                    sizes?.size ?: 0 > 2 -> sizes?.elementAt(2)
                    sizes?.size ?: 0 > 3 -> sizes?.elementAt(3)
                    else -> sizes?.first()
                }
            }
        }
            .cameraId(CAMERA_ID_0)
            .aspectRatio(ASPECT_RATIO_4_3)
            .usePreviewCallback(true, ANGLE_90))
            .action(FRAME_ACTION_NORMAL)
            .handler(handler)
            .lazyCallback(250L)
            .start()

        mBinding.frontcamera.useTextureRender(null, object : CameraBuilder() {
            override fun stateCallback(): StateCallback? = null
            override fun previewSize(sizes: SortedSet<Size>?): Size? {
                return when {
                    sizes?.size ?: 0 > 2 -> sizes?.elementAt(2)
                    sizes?.size ?: 0 > 3 -> sizes?.elementAt(3)
                    else -> sizes?.first()
                }
            }

            override fun pictureSize(sizes: SortedSet<Size>?): Size? {
                return when {
                    sizes?.size ?: 0 > 2 -> sizes?.elementAt(2)
                    sizes?.size ?: 0 > 3 -> sizes?.elementAt(3)
                    else -> sizes?.first()
                }
            }
        }
            .cameraId(CAMERA_ID_1)
            .aspectRatio(ASPECT_RATIO_4_3)
            .usePreviewCallback(true, ANGLE_90))
            .action(FRAME_ACTION_NORMAL)
            .handler(handler)
            .lazyCallback(250L)
            .start()
    }

    private fun decodeNv21ToFile(data: ByteArray, w: Int, h: Int, @Angle angle: Int): String? {
        var fos: FileOutputStream? = null
        try {
            var imgW = w
            var imgH = h
            when (angle) {
                ANGLE_90, ANGLE_270 -> {
                    imgW = h
                    imgH = w
                }
            }
            val yuvImage = YuvImage(data, ImageFormat.NV21, imgW, imgH, null)
            val dir = Environment.getExternalStoragePublicDirectory("${Environment.DIRECTORY_DCIM}/temp")
            if (!dir.exists() && !dir.mkdirs()) return null
            val file = File(dir, "${System.currentTimeMillis()}.jpg")
            fos = FileOutputStream(file)
            yuvImage.compressToJpeg(Rect(0, 0, imgW, imgH), 100, fos)
            return file.path
        } catch (ignore: Exception) {
        } finally {
            fos?.close()
        }
        return null
    }

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    override fun onPause() {
        super.onPause()
        mBinding.backcamera.stop()
        mBinding.frontcamera.stop()
    }

    override fun onWindowFocusChanged(hasFocus: Boolean) {
        super.onWindowFocusChanged(hasFocus)
        if (!hasFocus) return
        window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_FULLSCREEN
                or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        when (event?.action) {
            MotionEvent.ACTION_UP -> {
                startActivity(Intent(this, EmptyActivity::class.java))
                finish()
            }
        }
        return super.onTouchEvent(event)
    }
}